import os
import traceback
from datetime import datetime
from typing import Dict, Any, List

from config import settings
from utils.code_parser import FunctionParser
from utils.file_utils import list_source_files, split_c_file
from .ai_scan import run_ai_scan
from .clang import run_clang_scan
from .cppcheck import run_cppcheck_scan


async def _generate_report(self, results: List[Dict[str, Any]]) -> Dict[str, Any]:
    """生成最终报告
    
    Args:
        results: 扫描结果列表
    """
    print("\n生成扫描报告...")
    try:
        return {
            "scan_time": datetime.now().strftime("%Y-%m-%d %H:%M:%S")
        }

    except Exception as e:
        print(f"生成报告时出错: {str(e)}")
        print(f"错误类型: {type(e).__name__}")
        print(f"错误堆栈: {traceback.format_exc()}")
        raise


class Scanner:
    def __init__(self, task_id: int = None):
        self.function_parser = FunctionParser()
        self.results = {}
        self.analysis_results = []
        self.task_id = task_id

    async def scan_project(self, project_path: str, scan_type: str = "all") -> Dict[str, Any]:
        """扫描整个项目"""
        print(f"\n开始扫描项目: {project_path}")
        print(f"扫描类型: {scan_type}")

        try:
            # 执行扫描
            results = await self._run_scan(project_path, scan_type)
            
            # 直接返回扫描结果
            return results

        except Exception as e:
            print(f"扫描过程出错: {str(e)}")
            print(f"错误类型: {type(e).__name__}")
            print(f"错误堆栈: {traceback.format_exc()}")
            raise

    async def _run_scan(self, project_path: str, scan_type: str) -> Dict[str, Any]:
        """运行扫描任务"""
        print(f"\n开始扫描项目: {project_path}")
        print(f"扫描类型: {scan_type}")
        
        # 检查目录是否存在
        if not os.path.exists(project_path):
            raise Exception(f"仓库目录不存在: {project_path}")
            
        # 创建扫描队列
        scan_queue = []
        source_files = list_source_files(project_path, settings.C_FILE_EXTENSIONS)
        print(f"找到 {len(source_files)} 个源文件")
        
        for file_path in source_files:
            try:
                # 尝试多种编码方式读取文件
                encodings = ['utf-8', 'gbk', 'gb2312', 'latin1', 'cp1252']
                content = None
                for encoding in encodings:
                    try:
                        with open(file_path, 'r', encoding=encoding) as f:
                            content = f.read()
                            break
                    except UnicodeDecodeError:
                        continue
                if not content:
                    print(f"无法读取文件: {file_path}")
                    continue
                    
                # 分割文件
                segments = split_c_file(content)
                print(f"文件 {file_path} 被分割为 {len(segments)} 个代码块")
                
                # 将分割后的片段添加到扫描队列
                for segment in segments:
                    scan_queue.append({
                        'path': file_path,
                        'name': segment.name,
                        'content': segment.content,
                        'start_line': segment.start_line,
                        'end_line': segment.end_line,
                        'context': segment.content
                    })
            except Exception as e:
                print(f"处理文件 {file_path} 时出错: {str(e)}")
                continue
                
        print(f"\n预处理完成，共有 {len(scan_queue)} 个待扫描片段")
        
        try:
            if scan_type == "all":
                # 运行所有扫描
                clang_results = await run_clang_scan(project_path)
                cppcheck_results = await run_cppcheck_scan(project_path)
                ai_results = await run_ai_scan(self.task_id, project_path, scan_queue)
                self.results = {
                    "clang": clang_results,
                    "cppcheck": cppcheck_results,
                    "ai": ai_results
                }
                return self.results
            elif scan_type == "clang":
                results = await run_clang_scan(project_path)
                self.results = {"clang": results}
                return results
            elif scan_type == "cppcheck":
                results = await run_cppcheck_scan(project_path)
                self.results = {"cppcheck": results}
                return results
            elif scan_type == "ai":
                # 对于AI扫描或自定义扫描类型，都使用AI扫描
                print(f"使用AI扫描处理扫描类型: {scan_type}")
                results = await run_ai_scan(self.task_id, project_path, scan_queue)
                self.results = {"ai": results}
                return results
            else:
                raise ValueError(f"不支持的扫描类型: {scan_type}")
        except Exception as e:
            print(f"扫描过程出错: {str(e)}")
            print(f"错误类型: {type(e).__name__}")
            print(f"错误堆栈: {traceback.format_exc()}")
            raise


async def scan_project_all(project_path: str, task_id: int = None) -> Dict[str, Any]:
    """运行所有扫描器"""
    print("\n运行所有扫描器...")
    results = {}

    try:
        # 运行clang扫描
        print("\n运行clang扫描...")
        results['clang'] = await run_clang_scan(project_path)

        # 运行cppcheck扫描
        print("\n运行cppcheck扫描...")
        results['cppcheck'] = await run_cppcheck_scan(project_path)

        # 运行AI扫描
        print("\n运行AI扫描...")
        results['ai'] = await run_ai_scan(task_id, project_path, [])

        return results

    except Exception as e:
        print(f"扫描过程出错: {str(e)}")
        print(f"错误类型: {type(e).__name__}")
        print(f"错误堆栈: {traceback.format_exc()}")
        raise
